package com.jspx.network.http.adapter;

import com.jspx.boot.EnvFactory;
import com.jspx.boot.environment.Environment;
import com.jspx.json.JSONObject;
import com.jspx.network.http.HttpClient;
import com.jspx.security.asymmetric.AsyEncrypt;
import com.jspx.security.symmetry.Encrypt;
import com.jspx.security.symmetry.impl.AESEncrypt;
import com.jspx.security.symmetry.impl.DESedeEncrypt;
import com.jspx.security.utils.EncryptUtil;
import com.jspx.txweb.util.TXWebUtil;
import com.jspx.utils.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.util.*;

/**
 * Created by Administrator on 2017/5/23.
 * http 请求
 *
 *
 */
public class HttpClientAdapter  implements HttpClient {
    public static final int SUCCESS = 200;  // OK: Success!
    protected org.apache.http.client.CookieStore cookieStore  = new BasicCookieStore();
    protected CloseableHttpClient httpClient;
    protected boolean useProxy = false;
    protected String proxyHost = "127.0.0.1";
    protected int proxyPort = 8087;
    protected String encode = Environment.defaultEncode;
    protected int bufferSize = 512;
    protected int connectionTimeout = 20000;
    protected int readTimeout = 20000;
    //当前实体对象
    protected HttpResponse httpResponse;
    final private static String cipherAlgorithm = "AES/CBC/PKCS7Padding";

    protected final Map<String, String> defaultHeaders  = new HashMap<>();

    protected String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url)
    {
        this.url = url;
    }

    public boolean isUseProxy() {
        return useProxy;
    }

    public void setUseProxy(boolean useProxy)
    {
        this.useProxy = useProxy;
    }

    public String getProxyHost() {
        return proxyHost;
    }

    public void setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
    }

    public int getProxyPort() {
        return proxyPort;
    }

    public void setProxyPort(int proxyPort) {
        this.proxyPort = proxyPort;
    }

    public String getEncode() {
        return encode;
    }

    public void setEncode(String encode) {
        this.encode = encode;
    }

    public int getBufferSize() {
        return bufferSize;
    }

    public void setBufferSize(int bufferSize) {
        this.bufferSize = bufferSize;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public int getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    public HttpClient build()
    {
        return build(null);
    }

    public HttpClient build(String url)
    {
        defaultHeaders.put("Charsert", Environment.defaultEncode);
        defaultHeaders.put("Content-Type", "application/x-www-form-urlencoded");
        defaultHeaders.put("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");

        if (useProxy)
        {
            //设置代理IP、端口、协议（请分别替换）
            HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");
            //把代理设置到请求配置
            RequestConfig defaultRequestConfig = RequestConfig.custom().setProxy(proxy).build();
            ///实例化CloseableHttpClient对象
            httpClient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).setDefaultCookieStore(cookieStore).build();
        } else
            httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
        if  (!StringUtil.isNULL(url)) this.url = url;
        return this;
    }

    public CookieStore getCookieStore()
    {
        return cookieStore;
    }

    /**
     * GET 请求
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public HttpResponse getHttpResponse(String url,Map<String, Object> parameterMap,Map<String, String> headers) throws Exception
    {
        URIBuilder uriBuilder = new URIBuilder(url);
        if (parameterMap!=null&&!parameterMap.isEmpty())
        {
            /** 添加参数的形式*/
            List<NameValuePair> param = getParam(parameterMap);
            uriBuilder.addParameters(param);
        }
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        if(headers != null&&!headers.isEmpty()){
            addHeaders(httpGet, headers);
        }
        return httpClient.execute(httpGet);
    }

    public String getString(String url,Map<String, Object> parameterMap,Map<String, String> headers) throws Exception
    {
        return EntityUtils.toString(getHttpResponse(url,parameterMap,headers).getEntity());
    }

    public String getString(String url,Map<String, Object> parameterMap) throws Exception
    {
        return EntityUtils.toString(getHttpResponse( url,parameterMap,defaultHeaders).getEntity());
    }

    public String getString(String url) throws Exception
    {
        return EntityUtils.toString(getHttpResponse( url,null,defaultHeaders).getEntity());
    }

    public String getString(Map<String, Object> parameterMap) throws Exception
    {
        return EntityUtils.toString(getHttpResponse( url,parameterMap,defaultHeaders).getEntity());
    }

    public byte[] getBytes(String url,Map<String, Object> parameterMap,Map<String, String> headers) throws Exception
    {
        return EntityUtils.toByteArray(getHttpResponse( url,parameterMap,headers).getEntity());
    }

    public byte[] getBytes(String url,Map<String, Object> parameterMap) throws Exception
    {
        return EntityUtils.toByteArray(getHttpResponse( url,parameterMap,defaultHeaders).getEntity());
    }

    public byte[] getBytes(String url) throws Exception
    {
        return EntityUtils.toByteArray(getHttpResponse( url,null,defaultHeaders).getEntity());
    }

    /**
     * 参数
     * @param parameterMap
     * @return
     */
    private static List<NameValuePair> getParam(Map<String, Object> parameterMap) {
        if (parameterMap==null) return null;
        List<NameValuePair> param = new ArrayList<NameValuePair>();
        for(Map.Entry<String, Object> entry : parameterMap.entrySet()){
            param.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
        }
        return param;
    }

    /**
     * POST 请求
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public String post(String url, Map<String, Object> params, Map<String, String> headers) throws ParseException, IOException
    {
        HttpPost httpPost = new HttpPost(url);
        if (params!=null&&!params.isEmpty())
        {
            UrlEncodedFormEntity postEntity = new UrlEncodedFormEntity(getParam(params), encode);
            httpPost.setEntity(postEntity);
        }
        if(headers != null&&!headers.isEmpty()){
             addHeaders(httpPost, headers);
        }
        httpResponse = httpClient.execute(httpPost);
        return EntityUtils.toString(httpResponse.getEntity());
    }

    public String post(String url, Map<String, Object> params) throws ParseException, IOException
    {
        return post( url,  params, defaultHeaders);
    }

    public String post(Map<String, Object> params) throws ParseException, IOException
    {
        return post( url,  params);
    }

    public String post(String url,JSONObject json, Map<String, String> headers) throws Exception
    {
        if (headers==null||headers.isEmpty()) return "need headers";
        HttpPost httpPost = new HttpPost(url);
        if(!headers.isEmpty()){
            addHeaders(httpPost, headers);
        }
        String requestedWith = headers.get("X-Requested-With");
        if (requestedWith!=null&&requestedWith.contains(Environment.rocSecret))
        {
            String k1 = RandomUtil.getRandomAlphanumeric(16);
            String  iv = RandomUtil.getRandomAlphanumeric(16);

            Encrypt symmetryEncrypt = (Encrypt) ClassUtil.newInstance(com.jspx.security.symmetry.impl.AESEncrypt.class.getName());
            symmetryEncrypt.setCipherIv(iv);
            symmetryEncrypt.setSecretKey(k1);
            symmetryEncrypt.setCipherAlgorithm(cipherAlgorithm);
            String data = symmetryEncrypt.getEncode(json.toString());
            String ps = k1+'-'+iv;

            AsyEncrypt asyEncrypt = EnvFactory.getAsymmetricEncrypt();
            byte[] key = asyEncrypt.encryptByPublicKey(ps.getBytes(Environment.defaultEncode),EncryptUtil.hexToByte(EnvFactory.getPublicKey()));
            JSONObject posts = new JSONObject();
            posts.put("keyType","rsa");
            posts.put("dataType","aes");
            posts.put("key",EncryptUtil.byteToHex(key));
            posts.put("data",data);
            json = posts;
        }
        if (json!=null)
        {
            StringEntity s = new StringEntity(json.toString(4));
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            httpPost.setEntity(s);
        }
        httpResponse = httpClient.execute(httpPost);
        return EntityUtils.toString(httpResponse.getEntity());
    }
    public String post(String url, JSONObject json) throws Exception
    {
        return post( url, json, defaultHeaders);
    }

    public String post(JSONObject json) throws Exception
    {
        return post( url, json, defaultHeaders);
    }

    public String getResponseString() throws ParseException, IOException
    {
        return EntityUtils.toString(httpResponse.getEntity());
    }
    public int getStatusCode() throws ParseException
    {
        if (httpResponse==null) return -1;
        return httpResponse.getStatusLine().getStatusCode();
    }

    /**
     * 添加头
     * @param httpRequest
     * @param headerMap
     */
    private static void addHeaders(HttpRequestBase httpRequest, Map<String, String> headerMap){
        for(Map.Entry<String, String> entry : headerMap.entrySet()){
            httpRequest.setHeader(entry.getKey(), entry.getValue());
        }
    }
    /**
     * 上传文件到指定URL
     * @param file
     * @param url
     * @return
     * @throws IOException
     */
    public String upload(File file, String url)
    {
        String response = "";
        if (!file.exists()) {
            return "file not exists";
        }
        PostMethod postMethod = new PostMethod(url);
        try {
            //----------------------------------------------
            // FilePart：用来上传文件的类,file即要上传的文件
            FilePart fp = new FilePart("file", file);
            Part[] parts = { fp };

            // 对于MIME类型的请求，httpclient建议全用MulitPartRequestEntity进行包装
            MultipartRequestEntity mre = new MultipartRequestEntity(parts, postMethod.getParams());
            postMethod.setRequestEntity(mre);
            //---------------------------------------------
            org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
            client.getHttpConnectionManager().getParams()
                    .setConnectionTimeout(50000);// 由于要上传的文件可能比较大 , 因此在此设置最大的连接超时时间
            int status = client.executeMethod(postMethod);
            if (status == HttpStatus.SC_OK) {
                InputStream inputStream = postMethod.getResponseBodyAsStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(
                        inputStream));
                StringBuffer stringBuffer = new StringBuffer();
                String str = "";
                while ((str = br.readLine()) != null) {
                    stringBuffer.append(str);
                }
                response = stringBuffer.toString();
            } else {
                response = "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放连接
            postMethod.releaseConnection();
        }
        return response;
    }

    public boolean download(String url,File file) throws Exception
    {
        return FileUtil.writeFile(file,getBytes(url));
    }

    public void setHeaders(Map<String, String> header)
    {
        defaultHeaders.putAll(header);
    }

    public void cleanHeaders()
    {
        defaultHeaders.clear();
    }

    public static void main(String[] args) throws Exception {
        HttpClient httpClient = new HttpClientAdapter();
        Map<String,String> param = new HashMap<String,String>();
        param.put("loginId","admin");
        param.put("method","manageLogin");
        param.put("password","111111");
        param.put("submit","登陆");
        param.put("uid","name");
        //http://192.168.0.200:8080/jbbs/payreturn.jhtml
        //http://www.jspx.net/jcms/htdoc/products.jhtml
       // httpClient.setEncode("gb2312");
        String out = httpClient.build().getString("http://www.modoopark.com/");
        System.out.println(out);
    }
}
